Multithreading
C# supports multithreaded programming. A multithreaded program contains two or more parts that can run concurrently. Each part of such a program is called a thread, and each thread defines a separate path of execution. Thus, multithreading is a specialized form of multitasking.
Multithreaded programming relies on a combination of features defined by the C# language and by classes in the .NET Framework. Because support of multithreading is built into C#, many of the problems associated with multithreading in other languages are minimized or eliminated.
There are two distinct types of multitasking: process-based and thread-based. It is important to understand the difference between the two. A process is, in essence, a program that is executing. Thus, process-based multitasking is the feature that allows your computer to run two or more programs concurrently. For example, it is process-based multitasking that allows you to run a word processor at the same time you are using a spreadsheet or browsing the Internet. In process-based multitasking, a program is the smallest unit of code that can be dispatched by the scheduler.
A thread is a dispatch able unit of executable code. In a thread-based multitasking environment, all processes have at least one thread, but they can have more. This means that a single program can perform two or more tasks at once. For instance, a text editor can be formatting text at the same time that it is printing, as long as these two actions are being performed by two separate threads.
Process-based multitasking handles the concurrent execution of programs. Thread-based multitasking deals with the concurrent execution of pieces of the same program.
The .NET Framework defines two types of threads: foreground and background. By default, when you create a thread, it is a foreground thread, but you can change it to a background thread. The only difference between foreground and background threads is that a background thread will be automatically terminated when all foreground threads in its process have stopped.
The classes that support multithreaded programming are defined in the System.Threading namespace. Thus, you will usually include this statement at the start of any multithreaded program:
using System.Threading;
C#’s multithreading system is built upon the Thread class, which encapsulates a thread of execution. The Thread class is sealed, which means that it cannot be inherited.
The classes available in the System. Threading namespace
Thread Class Methods
Public Properties of Thread
Thread States
The state of a thread can be obtained from the ThreadState property provided by Thread
ThreadState.Aborted |
ThreadState.AbortRequested |
ThreadState.Background |
ThreadState.Running |
ThreadState.Stopped |
ThreadState.StopRequested |
ThreadState.Suspended |
ThreadState.SuspendRequested |
ThreadState.Unstarted |
ThreadState.WaitSleepJoin |
The simplest way to create a thread is to create a new instance of the Thread class. The Thread constructor takes a single argument: a delegate type. The CLR provides the ThreadStart delegate class specifically for this purpose, which points to a method you designate. This allows you to construct a thread and to say to that thread "when you start, run this method."
Program on multithreading with another modal
using System;
using System.Threading;
class abc
{
string tName;
Thread t;
public abc(string name)
{
tName = name;
t=new Thread(this.run);
t.Start();
}
public void run()
{
Console.WriteLine(tName + " starting.");
for(int c=0;c<10;c++)
{
Thread.Sleep(500);
Console.WriteLine("In " + tName +", count is " + c);
}
Console.WriteLine(tName + " terminating.");
}
}
class MultiThread
{
public static void Main()
{
Console.WriteLine("Main thread starting.");
abc mt = new abc("Child #1");
for(int c=0;c<10;c++)
{
Console.Write(".");
Thread.Sleep(100);
}
Console.WriteLine("Main thread ending.");
}
}
Program on Multiple Threads
using System;
using System.Threading;
class abc
{
string tName;
Thread t;
public abc(string name)
{
tName = name;
t=new Thread(this.run);
t.Start();
}
public void run()
{
Console.WriteLine(tName + " starting.");
for(int c=0;c<10;c++)
{
Thread.Sleep(500);
Console.WriteLine("In " + tName +", count is " + c);
}
Console.WriteLine(tName + " terminating.");
}
}
class vision
{
public static void Main()
{
Console.WriteLine("Main thread starting.");
abc t1 = new abc("Child #1");
abc t2= new abc("Child #2");
abc t3= new abc("Child #3");
for(int c=0;c<10;c++)
{
Console.Write(".");
Thread.Sleep(1000);
}
Console.WriteLine("Main thread ending.");
}
}
Program on IsAlive and Join
using System;
using System.Threading;
class abc
{
string tName;
public Thread t;
public abc(string name)
{
tName = name;
t=new Thread(this.run);
t.Start();
}
public void run()
{
Console.WriteLine(tName + " starting.");
for(int c=0;c<10;c++)
{
Thread.Sleep(500);
Console.WriteLine("In " + tName +", count is " + c);
}
Console.WriteLine(tName + " terminating.");
}
}
class vision
{
public static void Main()
{
Console.WriteLine("Main thread starting.");
abc t1 = new abc("Child #1");
abc t2= new abc("Child #2");
abc t3= new abc("Child #3");
Console.WriteLine(t1.t.IsAlive());
Console.WriteLine(t1.t.IsAlive());
Console.WriteLine(t1.t.IsAlive());
t1.t.Join();
t2.t.Join();
t3.t.Join();
Console.WriteLine(t1.t.IsAlive());
Console.WriteLine(t1.t.IsAlive());
Console.WriteLine(t1.t.IsAlive());
Console.WriteLine("Main thread ending.");
}
}
Arguments to Thread
From the C#2.0 onwards we can pass an argument to a thread. To do so, you must use new forms of Start( ), the Thread constructor, and the entry point method. To start a thread we need to use ParameterizedThreadStart rather than ThreadStart delegate.
Program on parameterized thread
using System;
using System.Threading;
class abc
{
string tName;
public Thread t;
public abc(string name,int n)
{
tName = name;
t = new Thread(new ParameterizedThreadStart ( this.run));
t.Start(n) ;
}
public void run(object n)
{
Console.WriteLine(tName + " starting.");
for (int c = 0; c < (int)n; c++)
{
Thread.Sleep(500);
Console.WriteLine("In " + tName + ", count is " + c);
}
Console.WriteLine(tName + " terminating.");
}
}
class vision
{
public static void Main()
{
Console.WriteLine("Main thread starting.");
abc t1 = new abc("Child #1",3);
abc t2 = new abc("Child #2",5);
abc t3 = new abc("Child #3",4);
t1.t.Join();
t2.t.Join();
t3.t.Join();
Console.WriteLine("Main thread ending.");
string s = Console.ReadLine();
}
}
Thread Priorities
You can change a thread’s priority through the Priority property, which is a member of Thread.
ThreadPriority is an enumeration that defines the following five priority settings:
ThreadPriority.Highest
ThreadPriority.AboveNormal
ThreadPriority.Normal
ThreadPriority.BelowNormal
ThreadPriority.Lowest
The default priority setting for a thread is ThreadPriority.Normal.
Program on Thread Priority’s
using System;
using System.Threading;
class abc
{
public long c;
public Thread t;
static bool stop = false;
static string tName;
public abc(string name)
{
c = 0;
t = new Thread(this.run);
t.Name = name;
tName = name;
}
void run()
{
Console.WriteLine(t.Name + " starting.");
do
{
c++;
} while (stop == false );
Console.WriteLine(t.Name + " terminating.");
}
public void term()
{
stop = true;
}
}
class vision
{
public static void Main()
{
abc mt1 = new abc("High Priority");
abc mt2 = new abc("Low Priority");
mt1.t.Priority = ThreadPriority.AboveNormal;
mt2.t.Priority = ThreadPriority.BelowNormal;
mt1.t.Start();
mt2.t.Start();
Thread.Sleep(100);
mt1.term();
mt2.term();
mt1.t.Join();
mt2.t.Join();
Console.WriteLine();
Console.WriteLine(mt1.t.Name + " thread counted to " +
mt1.c);
Console.WriteLine(mt2.t.Name + " thread counted to " +
mt2.c);
}
}